package sifeap.pl.managedbean.usuarios;


import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;

import sifeap.bl.ejb.usuarios.UsuarioBLLocal;
import sifeap.entities.usuarios.valueobject.UsuarioVO;
import sifeap.pl.util.FacesUtils;

@RequestScoped
@ManagedBean(name = "loginManagedBean")
public class LoginManagedBean {

	private String usuario;
	private String password;
	
	private Subject subject;
	
	private UsuarioVO usuarioSesion;
	
	private boolean mostrarDesbloquearUsuario;
	
	public final static String USER_LOGIN = "userLogin";
	
	private final String MENSAJES_BUNDLE = "sifeap.pl.bundles.mensajes";
	
	@EJB
	private UsuarioBLLocal usuarioBL;
	
	public LoginManagedBean() {
		subject = SecurityUtils.getSubject();
	}
	
	public String autenticar() {
		//Intenta obtener los intentos de este usuario
		Integer intentosFallidos = (Integer) FacesUtils.getSessionAttribute("intentos_" + usuario);
		if (intentosFallidos == null) {
			//Es primera vez que intenta ingresar con este usuario
			intentosFallidos = 0;
		}
		
		UsernamePasswordToken token = new UsernamePasswordToken(this.usuario,this.password);
		try {
			//Busca el usuario que acaba de iniciar sesion y lo sube a la sesion
			usuarioSesion = usuarioBL.buscarPorId(usuario);
			
			//Verifica si el usuario esta bloqueado
			if (usuarioSesion != null && usuarioSesion.getUsuario() != null 
					&& usuarioSesion.getUsuario().getHabilitado().equalsIgnoreCase("0")) {
				try {
					mostrarDesbloquearUsuario = true;
					FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.login.usuariobloqueado"), false);
				} catch (Exception em) {}
				
				return null;
			}
			
			subject.login(token);
			
			FacesUtils.setSessionAttribute(LoginManagedBean.USER_LOGIN, usuarioSesion);
			
			//Verifica si debe cambiar clave
			if (usuarioSesion != null && usuarioSesion.getUsuario() != null 
					&& usuarioSesion.getUsuario().getRequierecambio().equalsIgnoreCase("1")) {
				//Requiere cambio de contrasena
				try {
					FacesUtils.addWarnMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.login.cambiarcontrasena"), true);
				} catch (Exception e) {}

				FacesUtils.setSessionAttribute("intentos_" + usuario, new Integer(0));
				return "/web/usuarios/cambiarContrasena.jsf?faces-redirect=true";
			}
			
			FacesUtils.setSessionAttribute("intentos_" + usuario, new Integer(0));
			return redireccionar();
		} catch (AuthenticationException ae) {
			FacesUtils.setSessionAttribute("intentos_" + usuario, (++intentosFallidos));
			//ae.printStackTrace();
			try {
				int intentosMaximo = Integer.parseInt(FacesUtils.getMensaje("sifeap.pl.bundles.configuraciones", "sifeap.login.numerointentos"));
				
				if (intentosFallidos.intValue() < intentosMaximo) {
					FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.login.incorrecto"), false);
				} else {
					if (usuarioSesion != null && usuarioSesion.getUsuario() != null) {
						//El usuario existe. Se debe bloquear...
						usuarioSesion.getUsuario().setHabilitado("0"); //Bloquea el usuario
						try {
							usuarioBL.modificar(usuarioSesion.getUsuario());
							mostrarDesbloquearUsuario = true;
							FacesUtils.addWarnMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.login.intentossuperados"), false);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			} catch (Exception e) {}
		} catch (Exception e) {
			try {
				FacesUtils.addErrorMessage(FacesUtils.getMensaje(MENSAJES_BUNDLE, "sifeap.login.error"), false);
			} catch (Exception em) {}
			e.printStackTrace();
		}
		
		return null;
	}
	
	private String redireccionar() {

		HttpServletRequest req = (HttpServletRequest) FacesContext
				.getCurrentInstance().getExternalContext().getRequest();
		String url = "/web/nuestraEmpresa/quienesSomos.jsf?faces-redirect=true";

		try {
			SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(req);
			if (savedRequest != null) {
				url = savedRequest.getRequestUrl();
				String ruta_contexto = WebUtils.getContextPath(req);
				if (url.startsWith(ruta_contexto)) {
					url = url.replaceAll(ruta_contexto, "");
				}
			}
			if (!url.matches("(\\?faces-redirect\\=\\w.*)$")) {
				url += "?faces-redirect=true";
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return url;
	}
	
	public String salir() {
		try {
			subject.logout();

			// Invalida la Sesion
			try {
				FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
			} catch (Exception e) {}

			return "/web/nuestraEmpresa/quienesSomos.jsf?faces-redirect=true";
		} catch (Exception e) {
			e.printStackTrace();
			FacesUtils.addErrorMessage(e.getMessage(), false);
		}
		return null;
	}

	public String getUsuario() {
		return usuario;
	}

	public void setUsuario(String usuario) {
		this.usuario = usuario;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	
	public boolean isMostrarDesbloquearUsuario() {
		return mostrarDesbloquearUsuario;
	}

	public void setMostrarDesbloquearUsuario(boolean mostrarDesbloquearUsuario) {
		this.mostrarDesbloquearUsuario = mostrarDesbloquearUsuario;
	}

	/**
	 * Verifica si el usuario ha iniciado la sesion
	 * @return
	 */
	public boolean isAutenticado() {
		if (subject.getPrincipal() != null) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Verifica si el usuario autenticado tiene los permisos enviados
	 * @param permisos Permisos que se desean verificar
	 * @return
	 */
	public static boolean tienePermisos(String ... permisos) {
		boolean permisoGeneral = false;
		
		try {
			Subject subjectTemp = SecurityUtils.getSubject();
			boolean[] permitidos = subjectTemp.isPermitted(permisos);
			if (permitidos != null) {
				for (int i = 0; i < permitidos.length; i++) {
					boolean permitido = permitidos[i];
					if (permitido) {
						permisoGeneral = true;
						break;
					}
				}
			}
		} catch (Exception e) {
			permisoGeneral = false;
			e.printStackTrace();
		}
		return permisoGeneral;
	}
	
	/**
	 * Obtiene el usuario que ha iniciado sesion
	 * @return UsuarioVO en sesion
	 */
	public UsuarioVO getUsuarioSesion() {
		return (UsuarioVO) FacesUtils.getSessionAttribute(USER_LOGIN);
	}
}
